package com.truckdispatching.http.base;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy.Type;
import java.net.URL;
import java.net.URLEncoder;
import java.util.zip.GZIPInputStream;

import org.apache.http.HttpStatus;

import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Proxy;
import android.net.Uri;
import android.webkit.URLUtil;

import com.truckdispatching.util.NetUtils;

public class HttpTask implements Runnable {
	private final int DEFAULT_CONN_TIMEOUT = 10000; // 10seconds
	private final int DEFAULT_READ_TIMEOUT = 10000; // 10seconds

	private RequestType mRequestType = RequestType.POST;

	private String mUrl;

	private byte[] mRequestData;

	private HttpTaskListener mHttpTaskListener;

	private boolean isCancel = false;

	public void setRequestType(RequestType type) {
		this.mRequestType = type;
	}

	public enum RequestType {
		POST, GET
	}

	public HttpTask(String url, byte[] requestdata, HttpTaskListener listener) {
		this.mUrl = url;
		this.mRequestData = requestdata;
		this.mHttpTaskListener = listener;
	}

	public void cancel() {
		isCancel = true;
	}

	@Override
	public void run() {
		if (!NetUtils.isNetConnected()) {
			mHttpTaskListener.onRequestError(-100, "网络连接失败，请检查网络！");
			return;
		}
		mUrl = encodeUrl(mUrl);
		if (isCancel) {
			return;
		}
		HttpURLConnection httpConnection = null;
		try {
			// 判断地址是否有效,如无效,则直接返回错误
			if (!checkUrlAvailable(mUrl)) {
				throw new HttpException(-1, "无效的网络请求地址");
			}
			httpConnection = getConnection(mUrl);
			if (isCancel) {
				httpConnection.disconnect();
				httpConnection = null;
				return;
			}
			httpConnection.setConnectTimeout(DEFAULT_CONN_TIMEOUT);
			httpConnection.setReadTimeout(DEFAULT_READ_TIMEOUT);
			if (mRequestType == RequestType.POST) {
				httpConnection.setRequestMethod("POST");
				httpConnection.setDoOutput(true);
				OutputStream ops = httpConnection.getOutputStream();
				if (mRequestData != null && mRequestData.length > 0) {
					ops.write(mRequestData);
					ops.flush();
				}
			} else {
				httpConnection.setRequestMethod("GET");
			}
			if (isCancel) {
				httpConnection.disconnect();
				httpConnection = null;
				return;
			} else {
				httpConnection.connect();
			}
			int iStatusCode = httpConnection.getResponseCode();
			if (iStatusCode != HttpStatus.SC_OK && iStatusCode != HttpStatus.SC_PARTIAL_CONTENT) {
				throw new HttpException(iStatusCode, httpConnection.getResponseMessage());
			}
			InputStream reader = httpConnection.getInputStream();
			String content = getResponseString(reader);
			if (mHttpTaskListener != null && !isCancel) {
				mHttpTaskListener.onRequestSuccess(content);
			}
		} catch (Exception e) {
			if (mHttpTaskListener != null && !isCancel) {
				if (NetUtils.isNetConnected()) {
					mHttpTaskListener.onRequestError(-1, "网络请求失败");
				} else {
					mHttpTaskListener.onRequestError(-1, "网络连接失败，请检查网络！");
				}
			}
		}
	}

	/**
	 * 为了防止url里面的图片名含有空格或其它不合理字符导致url非法的问题,将其进行转义
	 * 
	 * @param url
	 * @return
	 */
	private String encodeUrl(String url) {
		Uri tempUri = Uri.parse(url);
		String encodeUrl = new String(url);
		String oldPath = tempUri.getLastPathSegment();
		if (oldPath != null && oldPath.length() > 0) {
			String path = tempUri.getLastPathSegment();
			path = URLEncoder.encode(path);
			path = path.replace("+", "%20");
			encodeUrl = encodeUrl.replace(oldPath, path);
		}
		return encodeUrl;
	}

	private boolean checkUrlAvailable(String url) {
		if (URLUtil.isHttpUrl(url) || URLUtil.isHttpsUrl(url)) {
			return true;
		}
		return false;
	}

	private HttpURLConnection getConnection(String url) throws IOException {
		HttpURLConnection conn = null;
		String defaultHost = Proxy.getDefaultHost();
		String targetUrl = new String(url);
		int defaultPort = Proxy.getDefaultPort();
		URL hostUrl = null;

		NetworkInfo activeNetworkInfo = HttpManager.getInstance().getNetworkInfo();
		int type = -1;
		String exrea = null;
		if (activeNetworkInfo != null) {
			type = activeNetworkInfo.getType();
			exrea = activeNetworkInfo.getExtraInfo();
		}
		if (type == ConnectivityManager.TYPE_MOBILE && defaultHost != null && defaultPort > 0) {
			if (exrea != null
					&& (exrea.startsWith("cmwap") || exrea.startsWith("uniwap") || exrea.startsWith("3gwap"))) {
				String host = null;
				String path = null;
				int hostIndex = "http://".length();
				int pathIndex = targetUrl.indexOf('/', hostIndex);
				if (pathIndex < 0) {
					host = targetUrl.substring(hostIndex);
					path = "";
				} else {
					host = targetUrl.substring(hostIndex, pathIndex);
					path = targetUrl.substring(pathIndex);
				}
				conn = (HttpURLConnection) new URL("http://" + defaultHost + ":" + defaultPort + path).openConnection();
				conn.setRequestProperty("X-Online-Host", host);
			} else {
				// 1、某些机型extra会有null情况 并且有代理；
				// 2、APN_TYPE_CTWAP
				java.net.Proxy proxy = new java.net.Proxy(Type.HTTP, new InetSocketAddress(defaultHost, defaultPort));
				conn = (HttpURLConnection) new URL(targetUrl).openConnection(proxy);
			}
		} else { // 非mobile或者没有默认代理地址的情况下，不走proxy
			hostUrl = new URL(url);
			conn = (HttpURLConnection) hostUrl.openConnection();
		}
		return conn;
	}

	/**
	 * 解压GZip数据作为字符串返回
	 * 
	 * @param in
	 * @return
	 */
	private String getResponseGZIPString(InputStream in) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		byte[] iBuffer = new byte[1024];
		String json = null;
		int bytesRead = 0;
		try {
			GZIPInputStream gzipIs = new GZIPInputStream(in);
			while (true) {
				bytesRead = gzipIs.read(iBuffer);
				if (bytesRead <= 0) {
					break;
				}
				baos.write(iBuffer, 0, bytesRead);
			}
			json = new String(baos.toByteArray(), "utf-8");
		} catch (IOException e) {
		} finally {
			if (baos != null) {
				try {
					baos.close();
				} catch (IOException e) {
				}
				baos = null;
			}
		}
		return json;
	}

	/**
	 * 将流中数据作为字符串返回
	 * 
	 * @param in
	 */
	private String getResponseString(InputStream in) {
		String getStr = "";
		ByteArrayOutputStream baos = null;
		try {
			baos = new ByteArrayOutputStream();
			int iLength = 1024;
			int bytesRead = 0;
			byte[] buff = new byte[iLength];
			while (true) {
				bytesRead = in.read(buff);
				if (bytesRead < 1) {
					break;
				}
				baos.write(buff, 0, bytesRead);
			}
			getStr = new String(baos.toByteArray(), "utf-8");
		} catch (UnsupportedEncodingException e) {
		} catch (IOException e) {
		} finally {
			if (baos != null) {
				try {
					baos.close();
				} catch (IOException e) {
				}
				baos = null;
			}
		}
		return getStr;
	}
}
